/**
 *
 *
 */
package org.jiscinvolve.astrodabis.barberry.control;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.stereotype.Controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.RequestAttributes;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.beans.factory.annotation.Autowired;  

import org.jiscinvolve.astrodabis.barberry.common.core.Tag;
import org.jiscinvolve.astrodabis.barberry.common.core.Job;
import org.jiscinvolve.astrodabis.barberry.common.core.Womble;
import org.jiscinvolve.astrodabis.barberry.common.core.Account;

import org.jiscinvolve.astrodabis.barberry.common.core.Identifier;
import org.jiscinvolve.astrodabis.barberry.common.core.Identified;
import org.jiscinvolve.astrodabis.barberry.common.core.SimpleIdent;

import org.jiscinvolve.astrodabis.barberry.common.data.TapTable;
import org.jiscinvolve.astrodabis.barberry.common.data.TapColumn;
import org.jiscinvolve.astrodabis.barberry.common.data.TapService;

import org.jiscinvolve.astrodabis.barberry.common.core.exception.*;

/**
 * Base class for our MVC controllers.
 *
 */
@Controller
public class BaseController
    {

    /**
     * Our debug logger.
     * 
     */
    private static Log log = LogFactory.getLog(BaseController.class);

    /**
     * Session attribute name for the current user ID.
     * 
     */
    public static final String SESSION_UID = "astrodabis.uid" ;

    /**
     * Our Womble.
     * 
     */
    @Autowired
    protected Womble womble ;
    public Womble womble()
        {
        return this.womble ;
        }

    /**
     * Get the Session ID from a WebRequest.
     * 
     */
    public String sid(WebRequest request)
        {
        return request.getSessionId();
        }

    /**
     * Get the actor from the WebRequest sesion.
     *
     */
    public Account actor(WebRequest request)
        {
        //
        // Get the actor UID from our Session.
        Identifier ident = (Identifier) request.getAttribute(
            SESSION_UID,
            RequestAttributes.SCOPE_SESSION
            );
        //
        // If the UID is null, return null.
        if (null == ident)
            {
            return null ;
            }
        //
        // If the UID is not null.
        else {
            //
            // Try loading the actor Account and set the Session attribute.
            try {
                Account actor = womble.accounts().select(
                    ident
                    );
                if (actor == null)
                    {
                    log.warn("Unable to find user account from session [" + ident + "]");
                    }
                return actor ;
                }
            //
            // Anything goes wrong, log it and return null.
            catch (Exception ouch)
                {
                log.error("Exception while retrieving user Account [" + ident + "][" + ouch.getClass().getName() + "][" + ouch.getMessage() + "]");
                return null ;
                }            
            }
        }

    public static final String MISC_ERROR_PAGE = "error/misc-error" ;
    public static final String AUTH_ERROR_PAGE = "error/auth-error" ;
    public static final String FIND_ERROR_PAGE = "error/find-error" ;

    @ExceptionHandler(Exception.class)
    public ModelAndView miscException(
        Exception ouch,
        WebRequest request
        ){
        ModelAndView mav = new ModelAndView(
            MISC_ERROR_PAGE,
            RequestData.MODEL_ATTRIB,
            new RequestData(
                request,
                womble,
                actor(
                    request
                    )
                )
            );
        return mav;
        }

    @ExceptionHandler(PermissionException.class)
    public ModelAndView authException(
        Exception ouch,
        WebRequest request
        ){
        ModelAndView mav = new ModelAndView(
            AUTH_ERROR_PAGE,
            RequestData.MODEL_ATTRIB,
            new RequestData(
                request,
                womble,
                actor(
                    request
                    )
                )
            );
        return mav;
        }

    @ExceptionHandler(NotFoundException.class)
    public ModelAndView findException(
        Exception ouch,
        WebRequest request
        ){
        ModelAndView mav = new ModelAndView(
            FIND_ERROR_PAGE,
            RequestData.MODEL_ATTRIB,
            new RequestData(
                request,
                womble,
                actor(
                    request
                    )
                )
            );
        return mav;
        }
    }   

